/** @format */
/**
 *@desc: 字符串处理工具类
 *@author: ptt
 *@date 2023/12/18
 */

// --------------------
// 如何使用？
// 1. 在main.js 中加入：
// import handleStr from '@/utils/handleStr.js' // 处理字符串
// vue3版本中
// app.provide('$handleStr',handleStr) //使用provide  提供全局对象
// vue3版本中提供给vue2写法
// app.config.globalProperties.$handleStr = handleStr;
// vue2版本中
// Vue.prototype.$handleStr = handleStr; //使用原型挂载

// 2.其他组件中获取该对象的方法：
// vue3写法中
//const $handleStr = inject('$handleStr')
// vue2写法中
// inject:['$handleStr'],

const zeros = [0, -0, '0'];
const emptyArr = [
    NaN,
    null,
    undefined,
    false,
    '',
    ' ',
    '-',
    'null',
    'undefined'
]; // 无数据的集合
const handleStr = {
    /**
     *@desc: 文本溢出打点
     *@param:   1.初始文本【String】;
                2.最大长度【Number】;
     *@returns {String}  打点的文字
     *@use    handleStr.makeDots('这是一段长文本',4) // 这是一段...
     */
    makeDots: (str, len) => {
        let hasValue = handleStr.hasValue(str);
        //有值 且 长度超过指定长度
        if (hasValue && str.length > len) {
            return str.slice(0, len) + '...';
        }
        //有值 未超过指定长度
        else if (hasValue) {
            return str;
        }
        //无值
        else {
            return '-';
        }
    },

    /**
     *@desc: 判断是否有值 (一般用于if判断)
     *@param:   1. 基本数据类型 ;
                2. 是否把"0" 当作值来看,默认不传,表示把"0"作为值，传入任意有效数值,则表示把"0"当作无数据 【String】。
     *@returns {Boolean}  true有值 false无值
     *@use     handleStr.hasValue(0) // true 
               handleStr.hasValue(0,true) // false 
     */
    hasValue: (val, refuse0) => {
        // 判断数据类型
        let type = handleStr.checkType(val);
        if (type == 'Array') {
            return val.length > 0;
        } else if (type == 'Object') {
            return Object.keys(val).length > 0;
        } else {
            // 将0判断成无数据的情况
            if (refuse0) {
                return ![...emptyArr, ...zeros].includes(val);
            }
            // 将0判断成有数据的情况
            else {
                return !emptyArr.includes(val);
            }
        }
    },

    /**
     *@desc: 数据不存在时设置默认值
     *@param:  1. 传入的数据 ;
               2. 设置无数据时返回的值, 不传则默认无数据返回'-'
     *@returns {String}  原值或默认值
     *@use   handleStr.setDefault(null,'--') // --
     */
    setDefault: (val, defaultVal) => {
        let hasValue = handleStr.hasValue(val);
        if (hasValue) {
            return val;
        } else if (defaultVal) {
            return defaultVal;
        } else {
            return '-';
        }
    },

    /**
     *@desc: 检测数据类型
     *@param:  1.js数据（基本数据类型和引用数据类型）
     *@returns {String}  数据对应的类型
     *@use   handleStr.checkType('10.00') // String
     */
    checkType: val => {
        return Object.prototype.toString.call(val).slice(8).split(']')[0]; // Number String Array Object Function
    },

    /**
     *@desc: 字符串转数字
     *@param: 基本数据类型
     *@returns {Number}
     *@use   handleStr.toNum('10.00') // 10
     */
    toNum: val => {
        if (!handleStr.hasValue(val)) return 0; //无值时统统转换为0
        let type = Object.prototype.toString.call(val).slice(8).split(']')[0];
        let res = '';
        switch (type) {
            case 'String':
                res = Number(val);
                break;
            case 'Number':
                res = val;
                break;
        }
        return res;
    },

    /**
     *@desc: 保留小数点后x位数 ;
     *@param:  1.数字型字符串或数字 
               2.需要保留的小数点后几位 , 不传默认保留后两位
     *@returns {String}
     *@use   handleStr.toFixed(10.0000001) // 10.00
     */
    toFixed: (val, num = 2) => {
        const v = handleStr.toNum(val);
        return v.toFixed(num);
    },

    /**
     *@desc: 格式化汉字类型的时间 ;
     *@param:  1.表示时间的字符串，如2023年4月【string】
     *@returns {String}
     *@use  handleStr.timeFormat('2001年4月21日') // 2001-04-21 00:00:00
     */
    timeFormat: val => {
        // 定义将数字转换为两位字符的辅助函数
        function padNumber(num) {
            return num < 10 ? '0' + num : num.toString();
        }

        // 定义日期时间的正则表达式数组
        let regexArr = [
            /^(\d{4})年(\d{1,2})月(\d{1,2})日(\d{1,2})时(\d{1,2})分(\d{1,2})秒$/, // YYYY年MM月DD日HH时mm分ss秒
            /^(\d{4})年(\d{1,2})月(\d{1,2})号(\d{1,2})时(\d{1,2})分(\d{1,2})秒$/, // YYYY年MM月DD号HH时mm分ss秒
            /^(\d{4})年(\d{1,2})月(\d{1,2})日(\d{1,2})时(\d{1,2})分$/, // YYYY年MM月DD日HH时mm分
            /^(\d{4})年(\d{1,2})月(\d{1,2})号(\d{1,2})时(\d{1,2})分$/, // YYYY年MM月DD号HH时mm分
            /^(\d{4})年(\d{1,2})月(\d{1,2})日(\d{1,2})时$/, // YYYY年MM月DD日HH时
            /^(\d{4})年(\d{1,2})月(\d{1,2})号(\d{1,2})时$/, // YYYY年MM月DD号HH时
            /^(\d{4})年(\d{1,2})月(\d{1,2})日$/, // YYYY年MM月DD日
            /^(\d{4})年(\d{1,2})月(\d{1,2})号$/, // YYYY年MM月DD号
            /^(\d{4})年(\d{1,2})月$/ // YYYY年MM月
        ];

        for (let i = 0; i < regexArr.length; i++) {
            let matchArr = val.match(regexArr[i]);
            if (matchArr) {
                // 匹配成功，解析成目标格式
                let year = matchArr[1];
                let month = padNumber(matchArr[2]);
                let day = i == 0 ? padNumber(matchArr[3]) : '01';
                let hour = i == 0 ? padNumber(matchArr[4]) : '00';
                let minute = i == 0 ? padNumber(matchArr[5]) : '00';
                let second = i == 0 ? padNumber(matchArr[6]) : '00';
                let result =
                    year +
                    '-' +
                    month +
                    '-' +
                    day +
                    ' ' +
                    hour +
                    ':' +
                    minute +
                    ':' +
                    second;
                return result;
            }
        }

        // 没有匹配成功，返回原字符串
        return val;
    },

    /**
     *@desc: 用递归实现深拷贝 ;
     *@param:   对象/数组【Object】
     *@returns {Object} 拷贝后的数据
     *@use  handleStr.deepClone({a:{b:1}}) // {a:{b:1}}
     */
    deepClone: obj => {
        if (obj === null || typeof obj !== 'object') {
            return obj;
        }

        let copy;

        if (Array.isArray(obj)) {
            copy = [];
            for (let i = 0; i < obj.length; i++) {
                copy[i] = handleStr.deepClone(obj[i]);
            }
        } else {
            copy = {};
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    copy[key] = handleStr.deepClone(obj[key]);
                }
            }
        }

        return copy;
    }

    //其它……
};

export default handleStr;
